/*
 *  Brno University of Technology
 *
 *  Copyright (C) 2009-2010 by Brno University of Technology and the contributors
 *
 *  Complete list of developers available at our web site:
 *
 *       http://spl.utko.feec.vutbr.cz
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/.
 */

package cz.vutbr.feec.utko.ef.core;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;


/**
 * The Class Config of evolutionary framework.
 */
public class Config {

	/** The population size. */
	private int populationSize;

	/** The number of evolutions. */
	private int evolutions;

	/** The filename of configuration input. */
	private String fileName;

	/** The root individual type. */
	private String rootIndividualType;

	/** The mutation rate. */
	private double mutationRate = 0.5;

	/** The crossover rate. */
	private double crossoverRate = 0.5;

	/** The is removing with same fitness. */
	private boolean isRemovingWithSameFitness;

	/** The max tree height. */
	private int maxTreeHeight;

	/** The minimal fitness. */
	private Double minimalFitness;

	/**
	 * Instantiates a new config.
	 */
	public Config() {
		this.fileName = "config_default.ini";
	}

	/**
	 * Instantiates a new config.
	 * 
	 * @param fileName
	 *            the file name
	 */
	public Config(String fileName) {
		this.fileName = fileName;
	}

	/**
	 * Gets the crossover rate.
	 * 
	 * @return the crossover rate
	 */
	public double getCrossoverRate() {
		return crossoverRate;
	}

	/**
	 * Gets the number of evolutions to be performed.
	 * 
	 * @return the evolutions number
	 */
	public int getEvolutionsNumber() {
		return evolutions;
	}

	/**
	 * Gets the max tree height.
	 * 
	 * @return the max tree height
	 */
	public int getMaxTreeHeight() {
		return maxTreeHeight;
	}

	/**
	 * Gets the minimal fitness.
	 * 
	 * @return the minimal fitness
	 */
	public Double getMinimalFitness() {
		return minimalFitness;
	}

	/**
	 * Gets the mutation rate.
	 * 
	 * @return the mutation rate
	 */
	public double getMutationRate() {
		return mutationRate;
	}

	/**
	 * Gets the population size.
	 * 
	 * @return the population size
	 */
	public int getPopulationSize() {
		return populationSize;
	}

	/**
	 * Gets the root individual type.
	 * 
	 * @return the root individual type
	 */
	public String getRootIndividualType() {
		return rootIndividualType;
	}

	/**
	 * Checks if is removing with same fitness.
	 * 
	 * @return true, if is removing with same fitness
	 */
	public boolean isRemovingWithSameFitness() {
		return isRemovingWithSameFitness;
	}

	/**
	 * Sets the crossover rate.
	 * 
	 * @param crossoverRate the crossover rate
	 */
	public void setCrossoverRate(double crossoverRate) {
		this.crossoverRate = crossoverRate;
	}

	/**
	 * Sets the file name.
	 * 
	 * @param fileName
	 *            the new file name
	 */
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	/**
	 * Sets the mutation rate.
	 * 
	 * @param mutationRate the new mutation rate
	 */
	public void setMutationRate(double mutationRate) {
		this.mutationRate = mutationRate;
	}

	/**
	 * Update the config file.
	 */
	public void update() {
		Properties p = new Properties();
		try {
			p.load(new FileInputStream(this.fileName));
			populationSize = Integer.parseInt(p.getProperty("population.size"));
			evolutions = Integer.parseInt(p.getProperty("evolutions"));
			mutationRate = getDoubleParam(p, "mutation_rate", 0.0, false);
			crossoverRate = getDoubleParam(p, "crossover_rate", 0.0, false);

			// normalize rates
			// mutationRate = mutationRate / (mutationRate + crossoverRate);
			// crossoverRate = crossoverRate / (mutationRate + crossoverRate);

			rootIndividualType = p.getProperty("root_individual_type");
			maxTreeHeight = Integer.parseInt(p.getProperty("max_tree_height"));
			isRemovingWithSameFitness = Boolean.parseBoolean(p
					.getProperty("delete_with_equal_fitnesses"));
			
			minimalFitness = getDoubleParam(p, "minimal_fitness", Double.MIN_VALUE, true);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Gets the double param.
	 * 
	 * @param p the properties
	 * @param propertyName the property name
	 * @param defaultValue the default value
	 * @param isOptional the is optional
	 * 
	 * @return the double param
	 */
	private double getDoubleParam(Properties p, String propertyName,
			double defaultValue, boolean isOptional) {
		String tmp = p.getProperty(propertyName);
		Double res = defaultValue;
		if (tmp != null) {
			res = Double.parseDouble(tmp);
		} else if (!isOptional) {
			throw new RuntimeException("Parameter " + propertyName
					+ " was not specified in config file: " + this.fileName);
		}
		return res;
	}
}
